use serde::{Deserialize, Serialize};
use std::borrow::Borrow;
use tide::utils::After;
use tide::{Middleware, Next, Request, Response, Result, StatusCode, Body};

use serde_json::Value;

use std::env;

use http_client::h1::H1Client as Client;
use http_client::HttpClient;

use api::*;
use state::State;

mod data;
mod api;
mod node;
mod state;

fn init_log() -> tide::Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .chain(fern::log_file("output.log")?)
        .apply()?;
    Ok(())
}

#[async_std::main]
async fn main() -> tide::Result<()> {
    dotenv::dotenv().ok();

    // tide::log::start();
    // tide::log::with_level(tide::log::LevelFilter::Warn);
    let _ = init_log();

    let db = env::var("DATABASE_URL")?;
    let state = State::new(db.as_str()).await?;
    let mut app = tide::with_state(state);

    app.with(After(|mut response: Response| async move {
        response.insert_header("Access-Control-Allow-Origin", "*");
        response.insert_header("Access-Control-Allow-Method", "*");
        response.insert_header("Access-Control-Allow-Credentials", "true");
        Ok(response)
    }));

    app.at("/node").get(|req: tide::Request<State>| async move {
        let state = req.state();
        let sealers = state.show();

        let mut vec = Vec::new();
        for (_, sealer) in sealers {
            vec.push(sealer.node_name)
        }

        Ok(Body::from(Value::from(vec)))
    });

    app.at("/jobs/:key").get(sealing_jobs);

    app.listen("127.0.0.1:8020").await?;
    Ok(())
}
